from aiohttp import web
from util import getvalue_or_error
from bson import ObjectId
import urllib.parse
import json
import aiohttp
import traceback
import time
import logging
import pymongo
import asyncio


class Handler:
    def __init__(self):
        pass

    async def HelloHandler(self, request):
        return web.Response(text="Hello!")

    async def CreateTingdanHandler(self, request):
        try:
            await request.post()
            # parse author_id
            author_id = getvalue_or_error(request.POST, 'author_id')

            # parse comment
            comment = request.POST.get('comment', '')

            # insert into mongo
            now_time = int(time.time())
            data = {
                "author_id": author_id,
                "create_time": now_time,
                "update_time": now_time,
                "content": {},
                "comment": comment
            }
            tingdan = await request.app['mongo'].insert_one(data)
            return web.json_response({'data': tingdan, 'error_msg': ''},
                                     dumps=request.app['json_encoder'].encode)

        except Exception as e:
            logging.debug(traceback.format_exc())
            return web.json_response({'data': None, 'error_msg': str(e)}, status=400)

    async def GetTingdanByIDHandler(self, request):
        try:
            _id = request.match_info['id']
            _id = ObjectId(_id)

            res = await request.app['mongo'].find({'_id': _id})
            if len(res) == 0:
                return web.json_response({'data': None, 'error_msg': 'Tingdan _id doesn\'t exist!'}, status=404)

            return web.json_response({'data': res[0], 'error_msg': ''},
                                     dumps=request.app['json_encoder'].encode)

        except Exception as e:
            return web.json_response({'data': None, 'error_msg': str(e)}, status=400)

    async def GetTingdansHandler(self, request):
        try:
            if 'author_id' in request.GET:
                query = {'author_id': request.GET['author_id']}
            else:
                query = {}
            if 'page' in request.GET:
                page = int(request.GET['page'])
            else:
                page = 1
            if 'page_size' in request.GET:
                page_size = int(request.GET['page_size'])
            else:
                page_size = request.app['default']['get_page_size']
            if page <= 0:
                raise Exception("Invalid page!")
            if page_size <= 0:
                raise Exception("Invalid page_size!")
            skip = (page - 1) * page_size
            limit = page_size
            res = await request.app['mongo'].find(query, skip, limit, [('create_time', pymongo.DESCENDING)])

            return web.json_response({'data': res, 'error_msg': ''},
                                     dumps=request.app['json_encoder'].encode)

        except Exception as e:
            return web.json_response({'data': None, 'error_msg': str(e)}, status=400)

    async def UpdateTingdanByIDHandler(self, request):
        try:
            _id = request.match_info['id']
            _id = ObjectId(_id)

            res = await request.app['mongo'].find({'_id': _id})
            if len(res) == 0:
                return web.json_response({'data': None, 'error_msg': 'Tingdan _id doesn\'t exist!'}, status=404)
            else:
                await request.post()
                # parse content
                content = getvalue_or_error(request.POST, 'content')
                try:
                    content = json.loads(content)
                except Exception as e:
                    raise Exception("Content isn't a valid json: " + str(e))
                tingdan = await request.app['mongo'].update_one({'_id': _id}, {"$set": {"content": content, "update_time": int(time.time())}})

            return web.json_response({'data': tingdan, 'error_msg': ''},
                                     dumps=request.app['json_encoder'].encode)

        except Exception as e:
            return web.json_response({'data': None, 'error_msg': str(e)}, status=400)

    async def PurgeTingdanByIDHandler(self, request):
        try:
            _id = request.match_info['id']
            _id = ObjectId(_id)

            res = await request.app['mongo'].find({'_id': _id})
            if len(res) == 0:
                return web.json_response({'data': None, 'error_msg': 'Tingdan _id doesn\'t exist!'}, status=404)

            loop = asyncio.get_event_loop()
            await loop.run_in_executor(None, request.app['upyun'].purge, ['/v1/tingdans/' + str(_id)])

            return web.json_response({'data': res[0], 'error_msg': ''},
                                     dumps=request.app['json_encoder'].encode)

        except Exception as e:
            return web.json_response({'data': None, 'error_msg': str(e)}, status=400)

    async def CORSPutMethod(self, request):
        return web.Response(headers={'Access-Control-Allow-Methods': 'PUT'})

    async def AddWordHandler(self, request):
        return None
